home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
PCW_C.ARJ
/
INT24C.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-20
|
10KB
|
292 lines
/**********************************************************/
/* File Id. Int24c.C. */
/* Author. Stan Milam. */
/* Date Written. 11/05/89. */
/* */
/* (c) Copyright 1989-90 by Stan Milam */
/* */
/* Comments: This code will be responsible for installing */
/* a Critical Interrupt Handler and handling of the crit- */
/* ical interrupt. The Interrupt code should check to see*/
/* if a window can be displayed, set the window colors, */
/* check the error to see if disk or device error. If disk*/
/* error display error message using subscript. If device*/
/* error try to determine device name and display in menu */
/* title. */
/* Research Material: */
/* PC Tech Magazine,April 1987,Exception Handling */
/* The MS-DOS Encycolpedia. */
/**********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "pcw.i"
#include "pcwproto.h"
/* Function Declarations */
#if __ZTC__
#define interrupt
void far *getvect( int nbr ) {
union REGS regs;
struct SREGS sregs;
regs.h.ah = (char) 0x35;
regs.h.al = (char) nbr;
int86x(0x21,®s,®s,&sregs);
return ( MK_FP(sregs.es, regs.x.bx) );
}
void setvect( int nbr, void far *isr ) {
union REGS regs;
struct SREGS sregs;
regs.h.ah = 0x25;
regs.h.al = (char) nbr;
regs.x.dx = FP_OFF(isr);
sregs.ds = FP_SEG(isr);
int86x(0x21,®s,®s,&sregs);
}
void (far *old_int24)(void);
#endif
#ifdef MSC
void (interrupt far *old_int24)(void);
#endif
#ifdef __TURBOC__
void interrupt (far *old_int24)(void);
#endif
#ifdef __POWERC
void interrupt (far *old_int24)(void);
#endif
extern void far interrupt Int24(void);
int far Critical_Interrupt(int ax, int di, char far *device);
void far _Save_ES_DS_(void);
/* Local Fucntion Declarations */
static void open_window(int ur, int uc, int lr, int lc);
static void close_window(int ur, int uc,int lr, int lc);
typedef struct { /* Device Driver Header */
int next_driver_offset;
int next_driver_segment;
int attribute;
int strategy_offset;
int interrupt_offset;
char device_name[8]; /* Only if character device */
}DEVHDR;
/* For Disk Block Device Errors */
static char *err_titles[] = {
" Diskette is Write Protected ",
" Invalid Disk Drive Number ",
" Disk Drive is Not Ready ",
" Unknown Device Command ",
" CRC Error ",
" Bad Request Structure Length ",
" Disk Seek Error ",
" Unknown Disk Media ",
" Disk Sector Not Found ",
" Printer Out of Paper ",
" Device Write Error ",
" Device Read Error ",
" General Error "," "," ",
" Invalid Disk Changing "
};
static char *disk_err_msg[] = {
"A critical interrupt has occured and",
"DOS has indicated the above problem",
"with a disk drive. Please choose",
"from the menu actions listed. ",
NULL
};
static char *non_disk_err[] = {
"A critical interrupt has occured and",
"DOS has indicated the above problem.",
"Please refer to the error message and",
"choose from the menu actions listed. ",
NULL
};
static char *err_menu[] = {
"1. Ignore the Error (Not Recommended)",
"2. Retry the Operation (Try Twice) ",
"3. Abort the Program (Last Resort) ",
"4. Fail the Operation (Better than 3)",
(char *) NULL
};
char far *_int24buf_; /* To hold screen contents */
/**********************************************************/
/* set_int24() */
/* */
/* Set INT 24 to point to our assembler routine, but first*/
/* save the address of the old interrupt handler to call */
/* it if we need to. */
/**********************************************************/
int set_int24(void) {
_int24buf_ = (char far *) malloc(1148); /* Malloc memory for window */
if (_int24buf_ == (char far *) NULL) return(0); /* Return if no memory */
#ifdef MSC
old_int24 = _dos_getvect(0x24); /* Get old int24 address */
_dos_setvect(0x24,Int24); /* Set Int 24 to point to */
#else /* Our code */
old_int24 = getvect(0x24);
setvect(0x24, Int24);
#endif
#ifdef __POWERC
_Save_ES_DS_(); /* Save Data & Extra Seg */
#endif
return(1);
}
/**********************************************************/
/* Critical_Interrupt */
/* */
/* This routine is called by the Assembler routine Int24. */
/* It will use the information passed to it to determine */
/* if the error was a disk error or a device error. If a */
/* device error we must determine if the device was a */
/* character device and display its name otherwise if it */
/* was a block device (has no name) we simply display a */
/* message stating " Block Device Error ". If the error */
/* was a disk error we display the message subscripted */
/* the value in Di and display the drive passed in the */
/* 8 lower bits of Ax. Pop up a menu and wait for user */
/* response in all cases. Return value in AX. */
/* If the return value in Ax is -1 the Assembler routine */
/* will restore the registers and call the original INT 24*/
/* handler. */
/**********************************************************/
int far Critical_Interrupt(int ax, int di, char far *device) {
char **msg;
char *wrkptr;
int mxr, mxc;
DEVHDR devhdr;
int uc = 20, lc = 60;
int tfclr = BLACK, mfclr = BLACK;
static char tmsg[38], dskmsg[31];
int choice, err_code, drive;
if (chk_video_state(&mxr, &mxc)) {
if (_int24buf_ == (char far *) NULL) return(-1);
if ( ax < 0) {
farcopy((void far *) &devhdr, device,sizeof(devhdr));
if (devhdr.attribute < 0) {
wrkptr = strchr(devhdr.device_name,32);
if (wrkptr != NULL) {
wrkptr++;
*wrkptr = 0;
}
strcpy(tmsg," Error In Device: ");
strncat(tmsg,devhdr.device_name,8);
}
else {
if (ax & 0x0200) strcpy(tmsg," Bad Memory Image of F.A.T. ");
else strcpy(tmsg, " Block Device Error ");
}
msg = non_disk_err; /* Use non disk message */
memset(dskmsg, '\0', 31); /* Clear & set disk message */
memset(dskmsg, 196, 30);
}
else { /* Disk Error */
err_code = di & 0x00ff;
drive = (ax & 0x00ff) + 65;
msg = disk_err_msg; /* Use disk error message */
strcpy(tmsg, err_titles[err_code]); /* Use table of error msgs */
strcpy(dskmsg,"Error in Drive %c:"); /* Use disk message */
}
/* Build the window, sound the alarm, and wait for user response */
if (mxc == 40) { /* Check max rows and adjust */
uc = 1;
lc = 40;
}
if (_monitor == COLOR) { /* Check for Color video */
tfclr = BLUE; /* And adjust if it is */
mfclr = RED;
}
open_window(6,uc,19,lc);
qputs(6,(mxc/2)-(strlen(tmsg)/2),tfclr,LIGHTGRAY,tmsg);
q_block_write(7,uc+2,BLACK,LIGHTGRAY,err_menu);
qprintf(12,CENTER,mfclr,LIGHTGRAY,dskmsg,drive);
q_block_write(14,uc+2,BLACK,LIGHTGRAY,msg);
_sound(880); rest(9); _nosound();
do {
choice = readkey();
/* if (choice == 0) choice = readkey() + 128; */
choice -= 49;
} while (choice < 0 || choice > 3);
close_window(6,uc,19,lc);
return(choice);
}
else return(-1); /* Call Original Int 24 */
}
/**********************************************************/
/* open_window */
/* */
/* Code to save screen image, color the window, draw the */
/* the border. */
/**********************************************************/
static void open_window(int ur, int uc, int lr, int lc) {
int far *scrnptr;
unsigned offset, scrnseg;
int rows, cols, page, pagesize;
int bfclr;
rows = (lr - ur) + 1;
cols = (lc - uc) + 1;
page = getpage();
pagesize = getpagesize();
scrnseg = getscrnseg();
offset = MK_SCRNOFF(ur,uc);
scrnptr = (int far *) MK_FP(scrnseg,offset);
SaveScrn(rows, cols, scrnptr, _int24buf_);
qfill(ur, uc, lr, lc,LIGHTGRAY, LIGHTGRAY, 32);
bfclr = (_monitor == COLOR) ? BROWN : BLACK;
bordercolor(bfclr,LIGHTGRAY);
setborder(DOUBLESIDES);
qbox(ur,uc,lr,lc);
}
/**********************************************************/
/* close_window */
/* */
/* Logic to remove the window. Uses PCW primatives. */
/**********************************************************/
static void close_window(int ur,int uc, int lr, int lc) {
int far *scrnptr;
unsigned offset, scrnseg;
int rows,cols,page,pagesize;
rows = (lr - ur) + 1;
cols = (lc - uc) + 1;
page = getpage();
pagesize = getpagesize();
scrnseg = getscrnseg();
offset = MK_SCRNOFF(ur,uc);
scrnptr = (int far *) MK_FP(scrnseg,offset);
RestoreScrn(rows, cols, scrnptr, _int24buf_);
}